import Root from "./Root";
import PropTypes from "prop-types";

import { Button, Checkbox, Col, DatePicker, Form, Input, InputNumber, Modal, Row, Select, TimePicker, Tree } from "antd";
import "braft-editor/dist/index.css";

const MonthPicker = DatePicker.MonthPicker;
const RangePicker = DatePicker.RangePicker;
const Search = Input.Search;
const FormItem = Form.Item;
const InputGroup = Input.Group;

const formItemLayout = {
  hasFeedback: true
};
const DEF_MODAL_OPTION = {
  okText: "确定",
  cancelText: "取消",
  resetText: "重置"
};

const EDITOR_FILES_FIELD = "_files";

class BaseForm extends Root {
  static propTypes = {
    fields: PropTypes.array.isRequired,
    onSubmit: PropTypes.func,
    layout: PropTypes.string,
    isSearch: PropTypes.bool,
    isModal: PropTypes.bool,
    modal: PropTypes.object,
    isSubmit: PropTypes.bool,
    submitText: PropTypes.string,
    submitIcon: PropTypes.string,
    buttons: PropTypes.array
  };

  constructor(props) {
    super(props);
    this.state = {
      editorInsetFiles: []
    };
  }

  render() {
    let {
      form,
      layout,
      fields,
      isModal,
      isSearch,
      buttons,
      onClear, //Search专用
      onSubmit,
      isSubmit,
      submitText,
      submitIcon
    } = this.props;
    let buttonsView = [];
    if (isSubmit) {
      buttonsView.push(
        this._getButton({
          type: "primary",
          title: submitText,
          icon: submitIcon,
          size: "large",
          htmlType: "submit"
        })
      );
    } else if (isSearch) {
      let searchBtns = [
        {
          type: "primary",
          title: submitText,
          icon: "search",
          htmlType: "submit"
        },
        {
          type: "clear",
          title: "清除",
          icon: "redo",
          onClick: () => {
            this.props.form.resetFields();
            onClear();
          }
        }
      ];
      searchBtns.forEach((btn, index) =>
        buttonsView.push(this._getButton(btn, index))
      );
    }
    if (buttons) {
      if (buttons.length > 0) {
        buttons.forEach((btn, index) =>
          buttonsView.push(this._getButton(btn, index))
        );
      } else buttonsView.push(buttons);
    }
    const formView = (
      <Form layout={layout} onSubmit={e => {
        //submit 按钮回调
        if (onSubmit) {
          e.preventDefault();
          onSubmit(form);
        }
      }}>
        {this.getFieldsView(fields)}
        <Row>
          <Col span={24} style={{ textAlign: isSearch ? "right" : "center", padding: "20px" }}>
            {buttonsView}
          </Col>
        </Row>
      </Form>
    );

    return isModal ? this.getModalView(formView) : formView;
  }

  /**
   * 构建Form 底部单个 Button
   */
  _getButton(btn, index) {
    let { title, onClick, type } = btn;
    //避免冲突onClick
    let event = onClick;
    delete btn.onClick;

    return (
      <Button
        {...btn}
        key={`${type}_${index}`}
        style={{ marginRight: 8 }}
        onClick={() => {
          if (event) event(this.props.form, type);
        }}
      >
        {title}
      </Button>
    );
  }

  getModalView(formView) {
    let { modal, form } = this.props;
    let okFunc = modal.onOk;
    modal.onOk = () => {
      // console.log(this.refs.form)
      okFunc(form);
    };
    //拷贝默认Modal设置，自定义的优先
    modal = Object.assign(modal, DEF_MODAL_OPTION);
    //合并Footer Reset按钮属性
    if (modal.isReset) {
      delete modal.isReset;
      modal = Object.assign(modal, this.getFooter(modal, true));
    } else if (modal.footer) {
      // modal;
    }

    return <Modal {...modal}>{formView}</Modal>;
  }

  /**
   * 获取Footer的自定义重置按钮
   * @param {Modal-options} modal
   */
  getFooter(modal, isReset) {
    let footer = [];
    if (isReset) {
      let resetBtn = (
        <Button key="reset_btn" onClick={() => this.resetForm()}>
          {modal.resetText}
        </Button>
      );
      footer.push(resetBtn);
    }
    footer.push([
      <Button key="cancel_btn" onClick={modal.onCancel}>
        {modal.cancelText}
      </Button>,
      <Button key="ok_btn" onClick={modal.onOk} type="primary">
        {modal.okText}
      </Button>
    ]);
    return { footer };
  }

  resetForm() {
    this.props.form.resetFields();
  }

  /**
   * 表格内容字段视图构建
   */
  getFieldsView(fields, isChild) {
    let fieldList = [];
    if (!fields && !isChild) {
      throw new Error("fields/onOk/onCancel is required!");
    }
    for (let index in fields) {
      let field = fields[index];
      let { name, type, item, option, children } = field;
      item = Object.assign({}, formItemLayout, item);
      fieldList.push(
        this.getFormItemView({
          name,
          type,
          item,
          option,
          children: this.getFieldsView(children, true),
          component: this.getFieldComponentByType(field)
        })
      );
    }
    return this.props.isSearch ? <Row>{fieldList}</Row> : fieldList;
  }

  /**
   * 单个字段视图构建
   * @param {*} field
   */
  getFormItemView(field) {
    let { form, isSearch, rowColumn } = this.props;
    const { getFieldDecorator } = form;
    //文件类型直接返回组件，无需再度封装
    if (field.type === "checkbox" || field.type === "hidden") {
      delete field.item.hasFeedback;
      delete field.item.label;
    } else if (
      field.type === "file" ||
      field.type === "tree" ||
      field.type === "select"
    ) {
      delete field.item.hasFeedback;
    }
    let formItemView = null;
    if (field.type === "editor") {
      formItemView = [
        <FormItem key={field.name} {...field.item}>
          {getFieldDecorator(field.name, field.option)(field.component)}
        </FormItem>,
        <FormItem key={field.name + EDITOR_FILES_FIELD}>
          {getFieldDecorator(field.name + EDITOR_FILES_FIELD)(
            <Input type="hidden"/>
          )}
        </FormItem>
      ];
    } else {
      formItemView = (
        <FormItem key={field.name} {...field.item}>
          {getFieldDecorator(field.name, field.option)(field.component)}
        </FormItem>
      );
      if (isSearch) {
        let columnSize = 24 / rowColumn;
        formItemView = (
          <Col span={columnSize} key={field.name + "_col"}>
            {formItemView}
          </Col>
        );
      }
    }

    return formItemView;
  }

  /**
   * 根据Field参数类型构建出对应组件视图
   * @param {*} param0
   */
  getFieldComponentByType({ name, type, attr, com, item, children }) {
    let component = null;
    switch (type) {
      case "hidden":
      case "string":
      case "password":
        component = <Input type={type} {...attr} />;
        break;
      case "group":
        if (children) {
          component = (
            <InputGroup {...attr}>
              {children.map(item => this.getFieldComponentByType(item))}
            </InputGroup>
          );
        } else {
          component = <InputGroup {...attr}>{com}</InputGroup>;
        }
        break;
      case "number":
        component = <InputNumber {...attr} />;
        break;
      case "checkbox":
        component = <Checkbox {...attr}>{item.label}</Checkbox>;
        break;
      case "search":
        component = <Search {...attr} />;
        break;
      case "date":
        component = <DatePicker format="YYYY-MM-DD" {...attr} />;
        break;
      case "datetime":
        component = (
          <DatePicker showTime format="YYYY-MM-DD HH:mm:ss" {...attr} />
        );
        break;
      case "month":
        component = <MonthPicker {...attr} />;
        break;
      case "rangeDate":
        component = <RangePicker format="YYYY-MM-DD" {...attr} />;
        break;
      case "time":
        component = <TimePicker {...attr} />;
        break;
      case "select":
        component = <Select {...attr} />;
        break;
      case "tree":
        component = <Tree {...attr} />;
        break;
      default:
        component = com;
    }
    return component;
  }
}

export default Form.create()(BaseForm);
